﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;

using Qing.Lang;
using Qing.Proto;
using Qing.Std;

namespace Qing.Std {

    class CreatePort : Native {
        public override string Name { get; set; } = "创建套接字";
        public override string Desc { get; set; } = "参数1-字符串，返回套接字；根据参数1的套接字地址，创建套接字";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if(args.Count == 0) {
                return new Expr(TP.Obj, new PortObj(ctx));
            }else if (args[0].Tp == TP.Str) {
                return new Expr(TP.Obj, new PortObj(args[0].Str(), ctx));
            }
            return Expr.Err("创建套接字函数参数错误");
        }

    }


    class HttpRequest: Native {

        public override string Name { get; set; } = "http请求";
        public override string Desc { get; set; } = "参数1-字符串，参数2-字符串，可选参数3-对象，可选参数4-对象，可选参数5-逻辑，返回字符串|二进制；参数1是请求的方法GET或POST，参数2是HTTP请求的路径，参数3是要传送的数据，参数4是请求头，参数5为真时返回二进制，默认返回字符串";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if(args.Count < 2) {
                return Expr.Err("http请求函数参数不足");
            }

            if (args[0].Tp != TP.Str || args[1].Tp != TP.Str) {
                return Expr.Err("http请求函数参数错误");
            }

            string result = "";
            try {
                HttpWebRequest request = WebRequest.CreateHttp(args[1].Str());
                request.Proxy = null;
                request.Method = args[0].Str();

                string data = "";
                if (args.Count > 2) {
                    if (args[2].Tp == TP.Str) {
                        data = args[2].Str();
                    } else if (args[2].Tp == TP.Obj) {
                        ToJson toJson = new ToJson();
                        Expr jsonExpr = toJson.Run(new List<Expr>() { args[2] }, ctx);
                        data = jsonExpr.Str();
                        if(data == "{}") {
                            data = "";
                        }
                        request.ContentType = "application/json";
                    }
                }

                if (args.Count > 3 && args[3].Tp == TP.Obj) {
                    foreach (var key in args[3].Obj().Map.Keys) {
                        Expr val = args[3].Obj().Map[key];
                        if (val.Tp == TP.Str) {
                            request.Headers.Add(key, val.Str());
                        } else {
                            request.Headers.Add(key, val.ToStr());
                        }
                    }
                }

                if (data.Length > 0) {
                    byte[] bts = Encoding.UTF8.GetBytes(data);
                    request.ContentLength = bts.Length;
                    #region //【2】将创建Stream流对象的过程写在using当中，会自动的帮助我们释放流所占用的资源。OK
                    using (Stream wStream = request.GetRequestStream())         //using(){}作为语句，用于定义一个范围，在此范围的末尾将释放对象。
                    {
                        wStream.Write(bts, 0, bts.Length);
                    }
                    #endregion
                }

                HttpWebResponse response= (HttpWebResponse)request.GetResponse();
                if (args.Count > 4 && args[4].ToBool()) {
                    List<byte> bts = new List<byte>();
                    var stream = response.GetResponseStream();
                    while(true) {
                        int b = stream.ReadByte();
                        if (b < 0) {
                            break;
                        }
                        bts.Add((byte)b);
                    }
                    return new Expr(TP.Bin, bts.ToArray());
                }
                
                using (Stream responseStream = response.GetResponseStream()) {
                    using (StreamReader sReader = new StreamReader(responseStream)) {
                        result = sReader.ReadToEnd();
                    }
                }

                return new Expr(TP.Str, result);
            } catch (HttpRequestException e) {
                return new Expr(TP.Str, e.Message);
            } catch (WebException e) {
                try {
                    using (Stream responseStream = e.Response.GetResponseStream()) {
                        using (StreamReader sReader = new StreamReader(responseStream)) {
                            result = sReader.ReadToEnd();
                        }
                    }
                    return new Expr(TP.Str, result);
                } catch(Exception ex) {
                    return new Expr(TP.Str, e.Message);
                }
                
            } catch(Exception e) {
                return Expr.Err("http请求错误：：" + e.Message);
            }

            return Expr.Err("http请求函数参数错误");
        }

    }




}
